home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Mac OS USB DDK / Examples / KeyboardModule / KBDHIDEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-10  |  8.1 KB  |  295 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KBDHIDEmulation.c
  3.  
  4.     Contains:    Keyboard Emulation code
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <DriverServices.h>
  15. #include <USB.h>
  16.  
  17. #ifndef DDKBuild
  18. #include <USBPriv.h>
  19. #endif
  20.  
  21. #include "KeyboardModule.h"
  22.  
  23. extern    usbKeyboardPBStruct myKeyboardPB;
  24. extern    usbKeyboardPBStruct shimKeyboardPB;
  25.  
  26. void GetKeysPressed(USBHIDData * pKeysPressed);
  27.  
  28. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  29. {
  30.     myKeyboardPB.interruptRefcon = refcon;
  31.     myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
  32.     return 0;
  33. }
  34.  
  35. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  36. {
  37.     switch (theControlSelector)
  38.     {
  39.         case kHIDSetLEDStateByBits:
  40.             if (shimKeyboardPB.keyboardReady)
  41.             {
  42.                 shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
  43.     
  44.                 shimKeyboardPB.retryCount = kKeyboardRetryCount;
  45.                 shimKeyboardPB.delayLevel = 0;                            
  46.                 shimKeyboardPB.transDepth = 0;    
  47.                 
  48.                 shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                    /* Start with setting the interface protocol */
  49.                 KeyboardInitiateTransaction(&shimKeyboardPB.pb);
  50.             }
  51.             else
  52.             {
  53.                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Set LED request when keyboard is busy", myKeyboardPB.interfaceRef);
  54.                 return kUSBDeviceBusy;
  55.             }
  56.             break;
  57.             
  58.         case kHIDRemoveInterruptHandler:
  59.             myKeyboardPB.interruptRefcon = nil;
  60.             myKeyboardPB.pSavedInterruptRoutine = nil;
  61.             myKeyboardPB.pSHIMInterruptRoutine = nil;
  62.             break;
  63.             
  64.         case kHIDEnableDemoMode:
  65.             USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Demo Mode Enabled", myKeyboardPB.interfaceRef);
  66.             myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
  67.             myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
  68.             break;
  69.  
  70.         case kHIDDisableDemoMode:
  71.             USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Demo Mode Disabled", myKeyboardPB.interfaceRef);
  72.             myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
  73.             break;
  74.  
  75.         default:
  76.             return paramErr;
  77.     }
  78.     return 0;
  79. }
  80.  
  81. void GetKeysPressed(USBHIDDataPtr pKeysPressed)
  82. {
  83. UInt8    i,keycount;
  84.     
  85.     keycount = 0;
  86.     for (i = 0; i < kKeyboardModifierBits; i++)
  87.     {
  88.         if (myKeyboardPB.oldHIDReport[0] & (1 << i))
  89.         {
  90.             pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
  91.         }
  92.     }
  93.             
  94.     if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
  95.     {
  96.         for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  97.         {
  98.             if (myKeyboardPB.oldHIDReport[i] > 0x03)
  99.             {
  100.                 pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
  101.             }
  102.         }                                                        
  103.     }
  104.     pKeysPressed->kbd.keycount = keycount;
  105. }
  106.  
  107.  
  108. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  109. {
  110. HIDInterruptProcPtr * pHIDIntProcPtr;
  111. UInt32 * pInterruptRefcon;
  112.  
  113.     switch (theInfoSelector)
  114.     {
  115.         case kHIDGetCurrentKeys:
  116.             GetKeysPressed((USBHIDDataPtr)theInfo);
  117.             break;
  118.  
  119.         case kHIDGetInterruptHandler:
  120.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
  121.             *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
  122.             break;
  123.  
  124.         case kHIDGetInterruptRefcon:
  125.             pInterruptRefcon = (UInt32 *)theInfo;
  126.             *pInterruptRefcon = myKeyboardPB.interruptRefcon;
  127.             break;
  128.         
  129.         default:
  130.             return paramErr;
  131.     }
  132.     return 0;
  133. }
  134.  
  135. OSStatus USBHIDPollDevice(void)
  136. {
  137. #ifndef DDKBuild
  138.     USLPolledProcessDoneQueue();
  139. #endif
  140.     return kUSBNoErr;
  141. }
  142.  
  143. OSStatus USBHIDEnterPolledMode(void)
  144. {    
  145.     return unimpErr;
  146. }
  147.  
  148. OSStatus USBHIDExitPolledMode(void)
  149. {
  150.     return unimpErr;
  151. }
  152.  
  153. void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  154. {
  155. #pragma unused (devicetype)
  156. static    UInt8    keydebug = 0;
  157.  
  158. UInt8    i, j, newkey, oldkey, deltas;
  159.  
  160. UInt8        changedmodifiers, keycount;
  161. USBHIDData    theKeyboardData;
  162. Boolean        keypressedflag, keyreleasedflag;
  163.     
  164.     deltas = 0;
  165.     
  166.     if (myKeyboardPB.hidEmulationInit == false)
  167.     {
  168.         myKeyboardPB.hidEmulationInit = true;
  169.         for (i = 0; i < kKeyboardReportSize; i++)
  170.             myKeyboardPB.oldHIDReport[i] = 0;
  171.     };
  172.     
  173.     myKeyboardPB.oldHIDReport[1] = 0x0;
  174.     hidReport[1] = 0x0;
  175.     
  176.     for (i = 0; i < kKeyboardReportSize; i++)
  177.     {
  178.         if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
  179.         {
  180.             deltas++;
  181.         }
  182.     }
  183.     
  184.     if ((myKeyboardPB.sendRawReportFlag) && deltas)
  185.     {
  186.         (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
  187.     }
  188.     else
  189.     {
  190.         if (deltas)
  191.         {
  192.             keycount = 0;
  193.             changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
  194.             
  195.             if (changedmodifiers)
  196.             {
  197.                 for (i = 0; i < kKeyboardModifierBits; i++)
  198.                 {
  199.                     if (changedmodifiers & (1 << i))
  200.                     {
  201.                         if (hidReport[0] & (1 << i))
  202.                         {
  203.                             if (keydebug++ < 8)
  204.                             {
  205.                                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Modifier key pressed: ", (0xe0 + i));
  206.                             }
  207.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
  208.                         }
  209.                         else
  210.                         {
  211.                             if (keydebug++ < 8)
  212.                             {
  213.                                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Modifier key released:", (0xe0 + i));
  214.                             }
  215.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
  216.                         }
  217.                     }
  218.                 }
  219.                 myKeyboardPB.oldHIDReport[0] = hidReport[0];
  220.             }
  221.             
  222.             if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
  223.             {
  224.                 // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
  225.                 // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
  226.                 // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
  227.                 // by the host software comparing the contents of the previous report to the current report.  If two or 
  228.                 // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
  229.                 // would have otherwise resulted in multiple events in a single report".
  230.                 
  231.                 // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
  232.                 // check all the old keys against all the new keys...
  233.                 
  234.                 for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  235.                 {
  236.                     keypressedflag = true;
  237.                     newkey = hidReport[i];
  238.                     
  239.                     keyreleasedflag = true;
  240.                     oldkey = myKeyboardPB.oldHIDReport[i];                            
  241.                     for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                // then look through all the keys that were previously and are currently reported as pressed
  242.                     {                                    
  243.                         if (newkey == myKeyboardPB.oldHIDReport[j])        // was this new key already pressed?
  244.                         {                                
  245.                             keypressedflag = false;                        // if it was, then don't report it as being pressed.
  246.                         }
  247.                         
  248.                         if (oldkey == hidReport[j])                        // Is the old key still pressed?
  249.                         {                                
  250.                             keyreleasedflag = false;                    // If yes, then don't report it as being released
  251.                         }
  252.                     }
  253.                     if ((newkey > 0x03) && keypressedflag)
  254.                     {
  255.                         theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
  256.                     }
  257.                     
  258.                     if ((oldkey > 0x03) && keyreleasedflag)
  259.                     {
  260.                         theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
  261.                     }
  262.                     
  263.                     if (keycount > 20)                                    // a worse case scenario is:
  264.                     {                                                    // 4 modifier keys up
  265.                         break;                                            // the other 4 modifier keys down
  266.                     }                                                    // 6 previously reported keys up
  267.                 }                                                        // 6 newly reported keys down
  268.                                                                         // 6 + 6 + 4 + 4 = 20
  269.                 for (i = 0; i<kKeyboardReportSize; i++)
  270.                 {
  271.                     myKeyboardPB.oldHIDReport[i] = hidReport[i];
  272.                 };
  273.             }
  274.             
  275.             if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
  276.             {
  277.                 theKeyboardData.kbd.keycount = keycount;
  278.                 (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData);
  279.             }
  280.         }
  281.     }
  282. }
  283.  
  284.  
  285. USBHIDModuleDispatchTable TheHIDModuleDispatchTable =
  286. {
  287.     (UInt32)0,
  288.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  289.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  290.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  291.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  292.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  293.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  294. };
  295.